package org.lboot.rbac.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import lombok.Data;
import org.lboot.core.auth.anno.CheckRole;
import org.lboot.core.domain.ErrMsg;
import org.lboot.core.domain.ResponseDTO;
import org.lboot.core.exception.BusinessException;
import org.lboot.llog.anno.ApiLog;
import org.lboot.rbac.module.dept.SysDept;
import org.lboot.rbac.module.dept.SysDeptService;
import org.lboot.rbac.module.dept.params.DeptCreateParams;
import org.lboot.rbac.module.dept.params.DeptUpdateParams;
import org.lboot.rbac.module.user.SysUser;
import org.lboot.rbac.module.user.SysUserService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.lboot.starter.plugin.rsr.RsrTree;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.domain.Example;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @author kindear
 * 部门管理器
 */
@Slf4j
@RestController
@RequestMapping("system")
@AllArgsConstructor
@Api(tags = "部门管理")
//@RsrTree("系统管理")
public class DeptController {
    SysDeptService deptService;

    SysUserService userService;

    @ApiLog("组织管理")
    @PostMapping("depts")
    @ApiOperation(value = "部门新建",notes = "")
    @CheckRole(orPerm = "rbac:dept:create")
    public ResponseDTO<SysDept> deptCreate(@Validated @RequestBody DeptCreateParams params){
        /* 初始化构建 **/
        SysDept sysDept = new SysDept();
        // 重复拦截
        sysDept.setDeptName(params.getDeptName());
        Example<SysDept> example = Example.of(sysDept);
        List<SysDept> depts = deptService.getExample(example);
        if (!depts.isEmpty()){
            throw new BusinessException(HttpStatus.BAD_REQUEST, ErrMsg.build("存在重复部门"));
        }
        BeanUtil.copyProperties(params,sysDept, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        /*
          如果是null 赋值为0
         */
        if(Validator.isEmpty(params.getParentId())){
            params.setParentId(0L);
        }


        return ResponseDTO.succData(deptService.saveOne(sysDept));
    }


    @ApiLog("RBAC")
    @DeleteMapping("depts/{deptId}")
    @ApiOperation(value = "部门删除",notes = "")
    @CheckRole(orPerm = "rbac:dept:delete")
    public ResponseDTO<Object> deptDelete(@PathVariable("deptId") Long deptId){
        // 判断部门是否存在子部门
        SysDept dept = new SysDept();
        dept.setParentId(deptId);
        Example<SysDept> example = Example.of(dept);
        List<SysDept> depts = deptService.getExample(example);
        if (!depts.isEmpty()){
            throw new BusinessException(HttpStatus.FORBIDDEN,ErrMsg.build("请先删除子部门"));
        }
        // 判断是否存在用户
        SysUser user = new SysUser();
        user.setDeptId(deptId);
        Example<SysUser> userExample = Example.of(user);
        List<SysUser> users = userService.getExample(userExample);
        if (!users.isEmpty()){
            throw new BusinessException(HttpStatus.FORBIDDEN,ErrMsg.build("请先转移部门下用户"));
        }
        deptService.deleteOne(deptId);
        // 删除子部门

        return ResponseDTO.succMsg("删除成功");
    }
    /**
     * 部门信息修改
     * @TODO 需要阻止递归依赖的情况发生
     */
    @ApiLog("RBAC")
    @PutMapping("depts")
    @ApiOperation(value = "部门更新",notes = "")
    @CheckRole(orPerm = "rbac:dept:update")
    public ResponseDTO<SysDept> deptUpdate(@RequestBody @Validated DeptUpdateParams params){
        SysDept sysDept = deptService.getOneUnwrap(params.getId());
        BeanUtil.copyProperties(params,sysDept, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        if (params.getId().equals(params.getParentId())){
            throw new BusinessException(HttpStatus.BAD_REQUEST,ErrMsg.build("异常操作"));
        }
        if(Validator.isEmpty(params.getParentId())){
            params.setParentId(0L);
        }
        return ResponseDTO.succData(deptService.updateOne(sysDept));
    }

    @GetMapping("depts")
    @ApiOperation(value = "全部部门")
    public ResponseDTO<Object> deptAll(){
        List<SysDept> depts = deptService.getAll();
        return ResponseDTO.succData(
                depts
        );
    }

    @Data
    private class DeptOption{
        String name;
        String key;
        String id;
    }
    @GetMapping("depts/options")
    @ApiOperation(value = "全部部门(选项)")
    public ResponseDTO<Object> deptAllOptions(){
        List<SysDept> depts = deptService.getAll();
        List<DeptOption> options = new ArrayList<>();
        for (SysDept dept:depts){
            DeptOption option = new DeptOption();
            option.setId(String.valueOf(dept.getId()));
            option.setKey(String.valueOf(dept.getId()));
            option.setName(dept.getDeptName());
            options.add(option);
        }
        return ResponseDTO.succData(options);
    }


    @GetMapping("depts/tree")
    @ApiOperation(value = "部门选择树",notes = "")
    public ResponseDTO<Object> buildDeptTree(){
        List<SysDept> depts = deptService.getAll();
        //配置
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setWeightKey("deptSort");
        treeNodeConfig.setIdKey("id");
        // 最大递归深度
        treeNodeConfig.setDeep(4);
        List<Tree<String>> treeNodes = TreeUtil.build(depts, "0", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId().toString());
                    if (Validator.isNotEmpty(treeNode.getParentId())){
                        tree.setParentId(treeNode.getParentId().toString());
                    }else {
                        tree.setParentId("0");
                    }
                    tree.setWeight(treeNode.getDeptSort());
                    tree.setName(treeNode.getDeptName());
                    tree.putExtra("key",treeNode.getId());
                    tree.putExtra("deptName",treeNode.getDeptName());
                    tree.putExtra("leader",treeNode.getLeader());
                    tree.putExtra("mobile",treeNode.getMobile());
                    tree.putExtra("email",treeNode.getEmail());
                    tree.putExtra("status", treeNode.getStatus());
                });
        return ResponseDTO.succData(treeNodes);
    }

    @GetMapping("depts/{deptId}")
    @ApiOperation(value = "部门查询",notes = "")
    public ResponseDTO<Object> deptQuery(@PathVariable("deptId") Long deptId){
        Optional<SysDept> deptOp = deptService.getOne(deptId);
        return deptOp.<ResponseDTO<Object>>map(ResponseDTO::succData).orElseGet(() -> ResponseDTO.wrap(HttpStatus.NOT_FOUND));
    }
}
